<template>
  <form class="v-form">
    <slot></slot>
  </form>
</template>

<script lang="ts" setup>
import { provide } from 'vue'
import type { ValidateFieldsError } from 'async-validator'
import type {
  FormProps,
  FormItemContext,
  FormContext,
  FormValidateFailure,
  // FormInstance,
} from './types'
import { FormContextKey } from './types'

const props = defineProps<FormProps>()

const fields: FormItemContext[] = []
const addField: FormContext['addField'] = (field) => {
  fields.push(field)
}
const removeField: FormContext['removeField'] = (field) => {
  if (field.prop) {
    fields.splice(fields.indexOf(field), 1)
  }
}
const resetFields = (keys: string[] = []) => {
  const filterArr = keys.length
    ? fields.filter((field) => keys.includes(field.prop))
    : fields

  filterArr.forEach((field) => field.resetField())
}
const clear = (keys: string[] = []) => {
  const filterArr = keys.length
    ? fields.filter((field) => keys.includes(field.prop))
    : fields

  filterArr.forEach((field) => field.clearValidate())
}
const validate = async () => {
  let validationErrors: ValidateFieldsError = {}
  for (const field of fields) {
    try {
      await field.validate('')
    } catch (e) {
      const error = e as FormValidateFailure
      validationErrors = {
        ...validationErrors,
        ...error.fields,
      }
    }
  }
  if (Object.keys(validationErrors).length === 0) {
    return true
  }
  return Promise.reject(validationErrors)
}

provide(FormContextKey, {
  ...props,
  addField,
  removeField,
})

defineExpose({
  validate,
  resetFields,
  clear,
})
defineOptions({ name: 'VForm' })
</script>
<style lang="css" scoped></style>
